package com.tanhua.server.service;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.common.pojo.User;
import com.tanhua.common.pojo.UserInfo;
import com.tanhua.common.utils.UserThreadLocal;
import com.tanhua.dubbo.server.api.AudioApi;
import com.tanhua.dubbo.server.api.LikeAudioApi;
import com.tanhua.dubbo.server.api.UsersApi;
import com.tanhua.dubbo.server.pojo.Audio;

import com.tanhua.server.vo.AudioVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * 发送和接收语音
 */
@Service
@Slf4j
public class AudioService {
    //注入FastFileStorageClient
    @Autowired
    private FastFileStorageClient fastFileStorageClient;
    //注入fdfsWebServer
    @Autowired
    private FdfsWebServer fdfsWebServer;
    //注入audioApi
    @Reference(version = "1.0.0")
    private AudioApi audioApi;
    //注入redis模板
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    //注入UserInfoService
    @Autowired
    private UserInfoService userInfoService;
    //注入LikeAudioApi
    @Reference(version = "1.0.0")
    private LikeAudioApi likeAudioApi;
    //注入usersApi
    @Reference(version = "1.0.0")
    private UsersApi usersApi;


    private static final String SEND_AUDIO = "send_audio";
    private static final String ACCEPT_AUDIO = "accept_audio";

    /**
     * 发送语音
     *
     * @param file 发送的语音文件
     * @return
     */
    public String sendAudio(MultipartFile file) {
        //获取登录用户id
        Long userId = UserThreadLocal.get().getId();
        try {
            //1.上传语音(fastDFS)
            StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(),
                    StrUtil.subAfter(file.getOriginalFilename(), ".", true), null);
            //2.设置语音的保存路径
            String url = fdfsWebServer.getWebServerUrl() + storePath.getFullPath();
            //3.查询redis中的发送语音剩余的次数
            String key = SEND_AUDIO + userId;
            String count = redisTemplate.opsForValue().get(key);
            Map<String, Object> map = new HashMap<>();
            //4.判断
            if (null == count) {
                //还没有这个key,说明还没有发送语音，可以发送
                audioApi.sendAudio(url, userId);
                //发送完，就计数一次,一天后过期
                redisTemplate.opsForValue().set(key, "1", 24 * 60 * 60, TimeUnit.SECONDS);
                return "count=4";
            } else if (Convert.toInt(count) < 5) {
                //小于等于10 也可以发送
                audioApi.sendAudio(url, userId);
                //发送完计数一次，设置一天后过期
                count = Convert.toInt(count) + 1 + "";
                redisTemplate.opsForValue().set(key, count, 24 * 60 * 60, TimeUnit.SECONDS);
                return "count="+(5 - Convert.toInt(count));
            } else {
                log.info("发送语音次数用完了");
                //不满足条件不能发送
                return "-1";
            }

        } catch (IOException e) {
            log.error("出异常了"+e);
        }
        return null;
    }

    /**
     * 接收语音
     *
     * @return
     */
    public AudioVo accpetAudio() {
        //获取登录用户的id
        Long userId = UserThreadLocal.get().getId();
        //查询redis
        String key = ACCEPT_AUDIO + userId;
        //先判断redis然后在查询，如果次数已经达到了，先查数据库，然后在判断就多查询一次了
        try {
            String count = redisTemplate.opsForValue().get(key);
            if (null == count) {
                //还没有这个键，可以接收语音
                AudioVo audioVo = queryAudioList(userId);
                //增加redis的次数,过期时间一天
                redisTemplate.opsForValue().set(key, "1", 24 * 60 * 60, TimeUnit.SECONDS);
                //audioVo对象补上剩余次数这个属性
                audioVo.setRemainingTimes(4);
                return audioVo;
            } else if (Convert.toInt(count) <5) {
                //次数未用完，可以接收消息
                AudioVo audioVo = queryAudioList(userId);
                count = Convert.toInt(count) + 1 + "";
                //增加redis的次数,过期时间一天
                redisTemplate.opsForValue().set(key, count, 24 * 60 * 60, TimeUnit.SECONDS);
                //audioVo对象补上剩余次数这个属性
                audioVo.setRemainingTimes(5 - Convert.toInt(count));
                return audioVo;
            } else {
                //次数用完了
                log.info("接收语音次数用完了");
                return null;
            }
        } catch (Exception e) {
            log.error("出异常了"+e);
        }
        return null;

    }

    //随机获取一条语音，并数据封装到AudioVo
    private AudioVo queryAudioList(Long userId) {
        //查询mongodb数据库,获取所有的语音
        //设定每次查10条
        List<Audio> audios = audioApi.queryAudioList(1, 10);
        if (CollUtil.isEmpty(audios)){
            //没有数据
            return null;
        }
        //todo  排除喜欢过的
        //排除自己发的语音
        //交给迭代器去执行删除操作
        for (Iterator iterator = audios.iterator(); iterator.hasNext(); ) {
            Audio audio = (Audio) iterator.next();
            if (userId == audio.getUseId()) {
                iterator.remove();
            }
        }
        //从语音中,随机获取一条
        if (ObjectUtil.isEmpty(audios)){
            return null;
        }
         int i=0;
        if (audios.size()!=1){
            //防止只有一条数据报警
            //获取随机数
            i = RandomUtil.getRandom().nextInt(0, audios.size());
        }
        //获取这个语音对象
        Audio audio = audios.get(i);
        //找到这个语音对象的用户信息
        UserInfo userInfo = userInfoService.queryUserInfoByUserId(audio.getUseId());
        AudioVo audioVo = new AudioVo();
        //填充AudioVo对象
        audioVo.setAge(userInfo.getAge());
        audioVo.setAvatar(userInfo.getLogo());
        audioVo.setGender(userInfo.getSex().name().toLowerCase());
        audioVo.setId(userInfo.getUserId());
        audioVo.setNickname(userInfo.getNickName());
        audioVo.setSoundUrl(audio.getUrl());
        return audioVo;
    }

    /**
     * 喜欢该语音
     * @param sendUserId 发送语音的用户id
     * @param soundUrl  语音的存储地址
     * @return
     */
    public Boolean likeThisAudio(String sendUserId, String soundUrl) {
        //获取登录用户的id
        User user = UserThreadLocal.get();
        //调用dubbo服务
        Boolean b=likeAudioApi.likeThisAudio(sendUserId,soundUrl,user.getId());
        if (!b){
            return false;
        }
        //数据保存成功，查询是否是相互喜欢
        Boolean mutualLike = likeAudioApi.isMutualLike(sendUserId, soundUrl, user.getId());
        if (mutualLike){
            //如果是相互喜欢，就加为好友，并添加到环信
            Boolean aBoolean = usersApi.saveUsers(user.getId(), Convert.toLong(sendUserId));
            if (!aBoolean){
                log.info("已经是好友，加好友失败");
                //添加失败
                return false;
            }
            //添加成功，在添加到环信
            //Boolean aBoolean1 = huanXinApi.addUserToHx(user.getId(), Convert.toLong(sendUserId));
           /* if (!aBoolean1){
                log.info("加环信失败");
                //失败
                return false;
            }*/
            log.info("相互喜欢，保存数据成功了");
            return true;
        }
        //成功
        log.info("不是相互喜欢，保存数据成功了");
        return true;

    }
}
